/*
 * @lc app=leetcode.cn id=705 lang=typescript
 *
 * [705] 设计哈希集合
 */

// @lc code=start
class LinkNode {
  value: number | null;
  next: LinkNode | null;
  prev: LinkNode | null;
  constructor(value: number = null, next: LinkNode = null, prev: LinkNode = null) {
    this.value = value;
    this.next = next;
    this.prev = prev;
  }
  remove() {
    this.prev.next = this.next;
    this.next.prev = this.prev;
    this.next = this.prev = null;
  }

  insert(node: LinkNode) {
    const p = this.next;
    node.prev = this;
    node.next = p;
    this.next = node;
    p.prev = node;
  }
}

class HashLink {
  head: LinkNode;
  tail: LinkNode;
  constructor() {
    this.head = new LinkNode();
    this.tail = new LinkNode();
    this.head.next = this.tail;
    this.tail.prev = this.head;
  }

  add(key: number): void {
    const node = new LinkNode(key);
    this.head.insert(node);
  }

  remove(key: number): void {
    let p = this.head;
    while (p) {
      if (p.value === key) {
        p.remove();
      }
      p = p.next;
    }
  }

  contains(key: number): boolean {
    let p = this.head;
    while (p) {
      if (p.value === key) {
        return true;
      }
      p = p.next;
    }
    return false;
  }
}

class MyHashSet {
  data: HashLink[];
  capcity: number;
  constructor() {
    this.capcity = 100;
    this.data = new Array(this.capcity).fill(new HashLink());
  }

  private hash(key: number): number {
    return key % this.capcity;
  }

  add(key: number): void {
    const idx = this.hash(key);
    const hashlink = this.data[idx];
    if (hashlink.contains(key)) return;
    hashlink.add(key);
  }

  remove(key: number): void {
    const idx = this.hash(key);
    const hashlink = this.data[idx];
    if (!hashlink.contains(key)) return;
    hashlink.remove(key);
  }

  contains(key: number): boolean {
    const idx = this.hash(key);
    const hashlink = this.data[idx];
    return hashlink.contains(key);
  }
}

/**
 * Your MyHashSet object will be instantiated and called as such:
 * var obj = new MyHashSet()
 * obj.add(key)
 * obj.remove(key)
 * var param_3 = obj.contains(key)
 */
// @lc code=end
